package com.demo.common.jackson;

import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 自定义bean序列化修饰
 *
 * @author molong
 * @since 2023/5/30
 */
public class CustomBeanSerializerModifier  extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (BeanPropertyWriter writer : beanProperties) {
            if (isArrayType(writer)) {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullArrayJsonSerializer());
            } else if (isStringType(writer)) {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullStringJsonSerializer());
            } else if (isBigDecimal(writer)) {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullBigDecimalJsonSerializer());
            } else if (isNumberType(writer)) {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullNumberJsonSerializer());
            } else if (isBooleanType(writer)) {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullBooleanJsonSerializer());
            } else if (isLocalDateTimeType(writer)) {
                //指定LocalDateTime类型的序列化器
                JsonSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
                writer.assignSerializer(localDateTimeSerializer);
                writer.assignNullSerializer(new CustomNullValueSerializers.NullStringJsonSerializer());
            } else if (isLocalDateType(writer)) {
                JsonSerializer localDateSerializer = new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
                writer.assignSerializer(localDateSerializer);
                writer.assignNullSerializer(new CustomNullValueSerializers.NullStringJsonSerializer());
            } else if (isLocalTimeType(writer)) {
                //localtime
                if (Objects.isNull(writer.getAnnotation(JsonFormat.class))) {
                    JsonSerializer localTimeSerializer = new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"));
                    writer.assignSerializer(localTimeSerializer);
                }
                writer.assignNullSerializer(new CustomNullValueSerializers.NullStringJsonSerializer());
            } else {
                writer.assignNullSerializer(new CustomNullValueSerializers.NullObjectInstanceJsonSerializer(writer.getType().getRawClass()));
            }
        }
        return beanProperties;
    }

    private boolean isLocalTimeType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return LocalTime.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是LocalDateTime
     */
    private boolean isLocalDateTimeType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return LocalDateTime.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是数组
     */
    private boolean isLocalDateType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return LocalDate.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是数组
     */
    private boolean isArrayType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是String
     */
    private boolean isStringType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是数值类型
     */
    private boolean isNumberType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return Number.class.isAssignableFrom(clazz);
    }

    /**
     * 是否是boolean
     */
    private boolean isBooleanType(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.equals(Boolean.class);
    }

    /**
     * 是否是boolean
     */
    private boolean isBigDecimal(BeanPropertyWriter writer) {
        Class<?> clazz = writer.getType().getRawClass();
        return clazz.equals(BigDecimal.class);
    }

}